﻿using System;
using System.Reflection;
using System.Collections.Generic;
using Ue.Eagle.Runtime.Models;
using Ue.Eagle.Runtime.FileSystems.Dependencies;

namespace Ue.Eagle.Runtime.Loaders
{
    /// <summary>
    /// 插件信息
    /// </summary>
    public class PluginProbeEntry
    {
        public PluginDescriptor Descriptor { get; set; }

        /// <summary>
        /// 插件加载器
        /// </summary>
        public IPluginLoader Loader { get; set; }

        /// <summary>
        /// 优先级
        /// </summary>
        public int Priority { get; set; }

        /// <summary>
        /// 插件虚拟路径
        /// 核心插件为插件目录路径
        /// 其它插件为插件项目dll文件路径
        /// </summary>
        public string VirtualPath { get; set; }

        /// <summary>
        /// 插件相关文件虚拟路径
        /// </summary>
        public IEnumerable<string> VirtualPathDependencies { get; set; }
    }

    /// <summary>
    /// 插件依赖引用的dll信息
    /// 这里并不包括插件自身dll
    /// </summary>
    public class PluginReferenceProbeEntry
    {
        public PluginDescriptor Descriptor { get; set; }
        public IPluginLoader Loader { get; set; }
        public string Name { get; set; }
        public string VirtualPath { get; set; }
    }

    /// <summary>
    /// 加载插件需要引用的dll信息（编译过的插件，指插件自身dll AssemblyName）
    /// 或需要编译插件的信息（指插件路径 BuildProviderTarget）
    /// </summary>
    public class PluginCompilationReference
    {
        /// <summary>
        /// 编译过插件的AssemblyName
        /// </summary>
        public string AssemblyName { get; set; }

        /// <summary>
        /// 插件需要编译的目标，一般是需要编译插件的目录路径
        /// </summary>
        public string BuildProviderTarget { get; set; }
    }

    /// <summary>
    /// 插件加载器
    /// </summary>
    public interface IPluginLoader
    {
        /// <summary>
        /// 加载器优先级
        /// </summary>
        int Priority { get; }

        /// <summary>
        /// 加载器名称
        /// </summary>
        string Name { get; }

        /// <summary>
        /// 检测插件的依赖信息
        /// </summary>
        /// <param name="PluginDescriptor"></param>
        /// <returns></returns>
        IEnumerable<PluginReferenceProbeEntry> ProbeReferences(PluginDescriptor PluginDescriptor);

        /// <summary>
        /// 加载依赖信息
        /// </summary>
        /// <param name="reference"></param>
        /// <returns></returns>
        Assembly LoadReference(DependencyReferenceDescriptor reference);
        void ReferenceActivated(PluginLoadingContext context, PluginReferenceProbeEntry referenceEntry);
        void ReferenceDeactivated(PluginLoadingContext context, PluginReferenceProbeEntry referenceEntry);
        /// <summary>
        /// 根据插件的加载器检测插件是否为预编译模块
        /// 如果不是预编译模块，则就是动态编模块（DynamicPluginLoader）
        /// </summary>
        /// <param name="extension"></param>
        /// <param name="references"></param>
        /// <returns></returns>
        bool IsCompatibleWithModuleReferences(PluginDescriptor extension, IEnumerable<PluginProbeEntry> references);

        PluginProbeEntry Probe(PluginDescriptor descriptor);
        Plugin Load(PluginDescriptor descriptor);

        void PluginActivated(PluginLoadingContext ctx, PluginDescriptor extension);
        void PluginDeactivated(PluginLoadingContext ctx, PluginDescriptor extension);
        void PluginRemoved(PluginLoadingContext ctx, DependencyDescriptor dependency);

        //void Monitor(PluginDescriptor extension, Action<IVolatileToken> monitor);

        /// <summary>
        /// 根据给定的模块，返回一个需要编译一个组件的引用列表
        /// 每个引用可以是一个程序集名称或文件传递给BuildManager.GetCompiledAssembly（）方法（如一个模块。的csproj项目文件）
        /// </summary>
        IEnumerable<PluginCompilationReference> GetCompilationReferences(DependencyDescriptor dependency);

        /// <summary>
        /// 返回给定模块的依赖关系的列表（虚拟路径）。
        /// 如dll、cs、csproj等文件路径
        /// </summary>
        IEnumerable<string> GetVirtualPathDependencies(DependencyDescriptor dependency);
    }
}
